{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "6d4b7999-a84e-4c04-a045-cf3bc45e83d7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello anaconda\n"
     ]
    }
   ],
   "source": [
    "print(\"hello anaconda\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "86b654ee-1708-4ff0-8a68-8dcbac333a9c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 320x240 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# TicTacToe\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "\n",
    "plt.rcdefaults()\n",
    "plt.rcParams['figure.dpi'] = 50\n",
    "plt.rcParams['font.size'] = 20\n",
    "\n",
    "class Thing:\n",
    "    def __init__(self, name=''):\n",
    "        self.name = name\n",
    "    def __repr__(self):\n",
    "        return self.name\n",
    "\n",
    "class Problem(Thing):\n",
    "    def __init__(self, name):\n",
    "        super().__init__(name)\n",
    "\n",
    "class GameProblem(Problem):\n",
    "    def __init__(self, name):\n",
    "        super().__init__(name)\n",
    "    def check_win(self):\n",
    "        pass\n",
    "    \n",
    "class TicTacToe(GameProblem):\n",
    "    def __init__(self, name):\n",
    "        super().__init__(name)\n",
    "        self.map = np.zeros((3, 3))\n",
    "        # self.map = np.random.randint(0, 10, (3, 3))\n",
    "\n",
    "    def check_win(self, state_map=None):\n",
    "        if state_map is None:\n",
    "            state_map = self.map\n",
    "        check_map = np.concatenate([state_map.sum(axis=0),\n",
    "                                    state_map.sum(axis=1),\n",
    "                                    [state_map.trace()],\n",
    "                                    [np.flip(state_map, axis=1).trace()]])\n",
    "        if 3 in check_map:  # 玩家赢\n",
    "            return 1\n",
    "        elif 30 in check_map:  # Agent赢\n",
    "            return 2\n",
    "        else:\n",
    "            return 0\n",
    "\n",
    "    def draw(self):\n",
    "        sns.heatmap(self.map.clip(0, 2),\n",
    "                    cmap='Set3',\n",
    "                    center=0,\n",
    "                    annot=True,\n",
    "                    cbar=False)\n",
    "        plt.show()\n",
    "    \n",
    "game = TicTacToe('1')\n",
    "game.draw()\n",
    "# game.pick(1,1)\n",
    "game.check_win()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "edae1627-0f48-4a96-a150-d28c962f5422",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 320x240 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "玩家落子: 1 1\n",
      "Agent落子: 0 0\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 320x240 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "玩家落子: 1 2\n",
      "Agent落子: 1 0\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAARQAAADVCAYAAACWsw/cAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8ekN5oAAAACXBIWXMAAAexAAAHsQEGxWGGAAAMvklEQVR4nO3df2zV9b3H8Vd/0toeWkiFUuEgDEpJ6LyltgwIJVHT7oco0+n+2O5FXK7xoiTQYDSZiWFbxpZ0yrRWHJmIW9xYnD+wcakEsLUTVqjURcBaV0NZgAIWCu2AtvTcnK+zW5HTseub+z2ffp+P5KR8v4e273wIz/M533OSkxCJRCICAAOJFj8EAKIICgAzBAWAmWRdbV2rrvqvCIra7j6/RwCGuXVazbBjdigAzBAUAGYICgAzBAWAGYICwAxBAWCGoAAwQ1AAmCEoAMwQFABmCAoAMwQFgBmCAsAMQQFghqAAMENQAJghKADMEBQAZggKADMEBYAZggLADEEBYIagADBDUACYISgAHPrkwDj17Oa/6M36TrUf6lHamCQVFWZrzYpZmj410+/RnNS49bDeeqlDZ0/1KW96pr65Il/hWVl+j+WkRofXMrA7lKZ9XfrOnWH9buN8bfp5iQYGIvreqj3627kBv0dzzr76Tm3d2Kby707T6uoS7z/BL77forOn+ejUoK1lYIPyy/UluuMbkzVzekgFM8fqJ48W6six89r/wRm/R3NOw8sd+spXr1NpeZ5yp2bqzpUFShmTpKa6I36P5pwGx9dyxKc8J0+e1HPPPaddu3bp2LFj3rnc3FwtWLBA99xzj6699lqNFmd7Pt2ZZI1N8XsUpwz0D+qvbWd107evHzqXmJig/KJxOnSw29fZXDMwCtYy5g5lz549ys/P15NPPqmsrCyVlZV5t+ifo+cKCgq0d+9ejQaDgxH9eP1Bzf3yOOV/KeT3OE7pPdPvrV8oO3XY+czsVO8aAIK1ljF3KCtXrtRdd92lDRs2KCEhYdh9kUhE999/v/d3oruXy6mrq/NuFQsOqeKmqYpna6v2q629Ry8+O8/vUQCnxQzKe++9p+eff/5zMYmKnlu9erWKiopi/uCKigrvpq5Vimc/qNqvt/54Qr9+Zp5yJ6T7PY5zMsameNvySy8a9pzuU2jc8EdajP61jPmUJ3qtpKmpKeY3Ru+bOHGiXBXdZUVjsq2+U5urSzUl7xq/R3JSckqiJs8Mqa2la+hcdNve1nJKU2e78VJnvEgeBWsZc4eyZs0a3XfffWpubtbNN988FI/Ozk5t375dGzduVFVVlVy1tuqAat88opqfzlXGNck68ckF73woI1lpaUl+j+eUsjvC+m3VAU2ZOVbhWWPV8EqH+s5fVGn5JL9Hc06Z42uZEIk+VMewZcsWPfHEE15ULl686J1LSkpScXGxKisrdffdd//r3xCnT3lmzf/DZc+ve7TQezk5HtV298X9m7HOnLqg66aHtPR/8jW1wI1H1XjT6NBa3jqt5sqD8pn+/n7vJeSonJwcpaT8Gy+txmlQXBTPQUEwXRqUK3rrfTQgkya5seUC4J/AvlMWgD2CAsAMQQFghqAAMENQAJghKADMEBQAZggKADMEBYAZggLADEEBYIagADBDUACYISgAzBAUAGYICgAzBAWAGYICwAxBAWCGoAAwQ1AAmCEoAMwQFABmCAoAM1f0QV+ID+kvfMvvEYDhHht+yA4FgBmCAsAMQQFghqAAMENQAJghKADMEBQAZggKADMEBYAZggLADEEBYIagADBDUACYISgAzBAUAGYICgAzBAWAGYICwAxBAWCGoAAwQ1AAmCEoAMwQFABmCAoAM4H9oK9nN/9Fb9Z3qv1Qj9LGJKmoMFtrVszS9KmZfo/mnOxwtsILwhqbF9KY0Bi999s/62TrSb/HclK242sZ2B1K074ufefOsH63cb42/bxEAwMRfW/VHv3t3IDfozknKTVRPZ09an2j1e9RnJfk+FoGdofyy/Ulw45/8mih5n99h/Z/cEYlReN9m8tFn3zU5d3wxbm+loHdoVzqbM+nO5OssSl+jwI4i6BIGhyM6MfrD2rul8cp/0shv8cBghmUw4cP695775Xr1lbtV1t7j5744Q1+jwIENyhdXV3avHnzZe+rq6tTZWWl6nYcUjz7QdV+vfXHE9r8dKlyJ6T7PQ7gtBEvym7dunXEb25vb495X0VFhXdT1yrFo0gkoh/+7IC21XfqVzXzNCXvGr9HAkZ3UJYuXaqEhATvP18s0ftdtLbqgGrfPKKan85VxjXJOvHJBe98KCNZaWlJfo/nlKSUJKWP/8fuLn1cujInZqr/XL8unPl0XRGMtRwxKJMmTVJNTY1uv/32y97f0tKi4uJiueg3L3d4X//zgaZh59c9Wqg7vjHZp6ncFMoLqfieuUPH+RUzva9HWo7q4GsHfZzMPSHH13LEoERj0dzcHDMo/2r3Es9ad33N7xFGjdOHTmv72h1+jzEqnHZ8LUcMykMPPaTe3t6Y98+YMUM7d+68GnMBGG1BWbRo0YjfnJGRocWLF1vPBMBRvLENgBmCAsAMQQFghqAAMENQAJghKADMEBQAZggKADMEBYAZggLADEEBYIagADBDUACYISgAzBAUAGYICgAzBAWAGYICwAxBAWCGoAAwQ1AAmCEoAMwQFABmCAqA/58P+rJQ2913tX9FcPzXS35PAFzipmFH7FAAmCEoAMwQFABmCAoAMwQFgBmCAsAMQQFghqAAMENQAJghKADMEBQAZggKADMEBYAZggLADEEBYIagADBDUACYISgAzBAUAGYICgAzBAWAGYICwAxBAWCGoABw54O+4l3j1sN666UOnT3Vp7zpmfrminyFZ2X5PZZzWEc7Lq9loHco++o7tXVjm8q/O02rq0u8f7xffL9FZ0/zaYf/DtbRzj7H1zLQQWl4uUNf+ep1Ki3PU+7UTN25skApY5LUVHfE79GcwjraaXB8LQMblIH+Qf217axmFo0fOpeYmKD8onE6dLDb19lcwjraGRgFazliUM6dO6fGxkYdOHDgc/edP39eL7zwglzVe6Zfg4MRhbJTh53PzE71nrviyrCOdnpHwVrGDMqHH36o2bNnq6ysTIWFhVq8eLGOHj06dH93d7eWL18e8wfX1dWpsrJS7zZ02E8NwK2gPPzww5ozZ46OHz+u1tZWhUIhLVy4UB0dVxaIiooKPf7445pbFlY8yhib4m0nL73Y1XO6T6Fxwx8hEBvraCdjFKxlzKC88847WrdunXJycjRjxgy9/vrrXiQWLVqk9vZ2uS45JVGTZ4bU1tI1dC663WxrOaWps914iS4esI52kkfBWiaOdP0kOfkfb1NJSEjQM888oyVLlnhPf6JPiVxXdkdYf/rDEe3ZdlSdHb36/VMfqO/8RZWWT/J7NKewjnbKHF/LmG9sKygo0N69e73rKP+surra+3rbbbfJdUWLJ6q3u091v2rXmVMXdN30kP77R/+h0Lgxfo/mFNbRTpHja5kQiUQil7sj+nTn7bff1htvvHHZb1yxYoU2bNigwcHBEX9B7ccrbCYFEHdunVZzZUGxQlCA4AQlsG9sA2CPoAAwQ1AAmCEoAMwQFABmCAoAMwQFgBmCAsAMQQFghqAAMENQAJghKADMEBQAZggKADMEBYAZggLADEEBYIagADBDUACYISgAzBAUAGYICgAzBAWAGYICwMxV/6AvF9TV1XkfBI8vjrUM9lqyQ/n7PxxssJbBXkuCIjn3KBDPWMtgryVPeQCYYYcCwAxBAWCGoAAwE/igPP3007r++uuVlpamefPmqampye+RnNPQ0KAlS5YoLy9PCQkJevXVV/0eyUnr1q1TSUmJQqGQJkyYoKVLl6q1tVUuCXRQtmzZosrKSj322GN69913dcMNN3hX1o8fP+73aE7p7e311i4aZ/zf1dfX64EHHtDu3bu1bds29ff3q7y83FtfVwT6VZ7ojiT6iFBdXe0dDw4OasqUKVq5cqUeeeQRv8dzUnSH8sorr3iPrvhiTpw44e1UoqEpKyuTCwK7Q+nr61Nzc7NuueWWoXOJiYne8a5du3ydDYjq7u72vo4fP16uCGxQTp48qYsXL2rixInDzkePjx075ttcwGe75VWrVmnhwoWaM2eOXJHs9wAAPi96LeX9999XY2OjXBLYoOTk5CgpKUmdnZ3DzkePc3NzfZsLePDBB1VbW+u9ejZ58mS5JLBPeVJTU1VcXKzt27cP22ZGj+fPn+/rbAimSCTixSR6UXvHjh2aNm2aXBPYHUpU9CXjZcuW6cYbb1RpaanWr1/vvUS3fPlyv0dzSk9Pjz766KOh448//lgtLS3excRwOOzrbK49zXnxxRf12muvee9F+exaXlZWltLT0+WESMA99dRTkXA4HElNTY2UlpZGdu/e7fdIztm5c2f0rQefuy1btszv0Zyiy6xh9LZp06aIKwL9PhQAtgJ7DQWAPYICwAxBAWCGoAAwQ1AAmCEoAGTlfwF+nVyrjGPfFQAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 320x240 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "玩家落子: 2 2\n",
      "Agent落子: 2 1\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 320x240 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "该点已经有棋子\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 320x240 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# TicTacToe\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "\n",
    "plt.rcdefaults()\n",
    "plt.rcParams['figure.dpi'] = 50\n",
    "plt.rcParams['font.size'] = 20\n",
    "\n",
    "class Thing:\n",
    "    def __init__(self, name=''):\n",
    "        self.name = name\n",
    "    def __repr__(self):\n",
    "        return self.name\n",
    "\n",
    "class Problem(Thing):\n",
    "    def __init__(self, name):\n",
    "        super().__init__(name)\n",
    "\n",
    "class GameProblem(Problem):\n",
    "    def __init__(self, name):\n",
    "        super().__init__(name)\n",
    "    def check_win(self):\n",
    "        pass\n",
    "    \n",
    "class TicTacToe(GameProblem):\n",
    "    def __init__(self, name):\n",
    "        super().__init__(name)\n",
    "        self.map = np.zeros((3, 3))\n",
    "        # self.map = np.random.randint(0, 10, (3, 3))\n",
    "\n",
    "    def check_win(self, state_map=None):\n",
    "        if state_map is None:\n",
    "            state_map = self.map\n",
    "        check_map = np.concatenate([state_map.sum(axis=0),\n",
    "                                    state_map.sum(axis=1),\n",
    "                                    [state_map.trace()],\n",
    "                                    [np.flip(state_map, axis=1).trace()]])\n",
    "        if 3 in check_map:  # 玩家赢\n",
    "            return 1\n",
    "        elif 30 in check_map:  # Agent赢\n",
    "            return 2\n",
    "        else:\n",
    "            return 0\n",
    "\n",
    "    def draw(self):\n",
    "        sns.heatmap(self.map.clip(0, 2),\n",
    "                    cmap='Set3',\n",
    "                    center=0,\n",
    "                    annot=True,\n",
    "                    cbar=False)\n",
    "        plt.show()\n",
    "    \n",
    "# game = TicTacToe('1')\n",
    "# game.draw()\n",
    "# game.check_win()\n",
    "\n",
    "\n",
    "class RandomTicTacToe(TicTacToe):\n",
    "    def __init__(self, name):\n",
    "        super().__init__(name)\n",
    "\n",
    "    def agent_pick(self):\n",
    "        actions = np.concatenate([(np.where(self.map == 0))], axis=1).T\n",
    "        if len(actions) > 0:\n",
    "            x, y = actions[np.random.randint(0, len(actions))]\n",
    "            self.map[x, y] = 10\n",
    "            print(\"Agent落子:\", x, y)\n",
    "        else:\n",
    "            print(\"Agent已经无处落子\")\n",
    "\n",
    "    def pick(self, x, y):\n",
    "        if self.map[x, y] == 0:\n",
    "            self.map[x, y] = 1\n",
    "            print('玩家落子:', x, y)\n",
    "            self.agent_pick()\n",
    "        else:\n",
    "            print('该点已经有棋子')\n",
    "        if self.check_win() == 1:\n",
    "            print(\"玩家胜利\")\n",
    "        elif self.check_win() == 2:\n",
    "            print(\"Agent胜利\")\n",
    "        self.draw()\n",
    "\n",
    "game = RandomTicTacToe('RandomTicTacToe')\n",
    "game.draw()\n",
    "game.pick(1, 1)\n",
    "game.pick(1, 2)\n",
    "game.pick(2, 2)\n",
    "# 测试重复落子\n",
    "# game.pick(2,1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "d97da160-2219-478f-a8b3-20cab7f03c3d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 320x240 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "玩家落子: 0 1\n",
      "[(1, 0, -1), (1, 2, -1), (2, 0, -1), (2, 2, -1), (0, 0, 0), (0, 2, 0), (1, 1, 0), (2, 1, 0)]\n",
      "Agent落子: 2 1\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 320x240 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "玩家落子: 1 1\n",
      "[(1, 0, -1), (1, 2, -1), (0, 0, 0), (0, 2, 0), (2, 0, 0), (2, 2, 0)]\n",
      "Agent落子: 2 2\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 320x240 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "玩家落子: 0 0\n",
      "[(1, 0, -1), (1, 2, -1), (0, 2, 1), (2, 0, 1)]\n",
      "Agent落子: 2 0\n",
      "Agent胜利\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 320x240 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# TicTacToe\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "\n",
    "plt.rcdefaults()\n",
    "plt.rcParams['figure.dpi'] = 50\n",
    "plt.rcParams['font.size'] = 20\n",
    "\n",
    "class Thing:\n",
    "    def __init__(self, name=''):\n",
    "        self.name = name\n",
    "    def __repr__(self):\n",
    "        return self.name\n",
    "\n",
    "class Problem(Thing):\n",
    "    def __init__(self, name):\n",
    "        super().__init__(name)\n",
    "\n",
    "class GameProblem(Problem):\n",
    "    def __init__(self, name):\n",
    "        super().__init__(name)\n",
    "    def check_win(self):\n",
    "        pass\n",
    "    \n",
    "class TicTacToe(GameProblem):\n",
    "    def __init__(self, name):\n",
    "        super().__init__(name)\n",
    "        self.map = np.zeros((3, 3))\n",
    "        # self.map = np.random.randint(0, 10, (3, 3))\n",
    "\n",
    "    def check_win(self, state_map=None):\n",
    "        if state_map is None:\n",
    "            state_map = self.map\n",
    "        check_map = np.concatenate([state_map.sum(axis=0),\n",
    "                                    state_map.sum(axis=1),\n",
    "                                    [state_map.trace()],\n",
    "                                    [np.flip(state_map, axis=1).trace()]])\n",
    "        if 3 in check_map:  # 玩家赢\n",
    "            return 1\n",
    "        elif 30 in check_map:  # Agent赢\n",
    "            return 2\n",
    "        else:\n",
    "            return 0\n",
    "\n",
    "    def draw(self):\n",
    "        sns.heatmap(self.map.clip(0, 2),\n",
    "                    cmap='Set3',\n",
    "                    center=0,\n",
    "                    annot=True,\n",
    "                    cbar=False)\n",
    "        plt.show()\n",
    "\n",
    "# MiniMax\n",
    "class MinimaxTicTacToe(TicTacToe):\n",
    "    def __init__(self, name):\n",
    "        super().__init__(name)\n",
    "\n",
    "    def value(self, next_agent, map_state):\n",
    "        win = self.check_win(map_state)\n",
    "        if win == 1:\n",
    "            return -1\n",
    "        elif win == 2:\n",
    "            return 1\n",
    "        actions = np.concatenate([(np.where(map_state == 0))], axis=1).T  # self.map\n",
    "        if len(actions) > 0:\n",
    "            if next_agent == 'max':\n",
    "                return self.max_value(actions, map_state)\n",
    "            elif next_agent == 'min':\n",
    "                return self.min_value(actions, map_state)\n",
    "        else:\n",
    "            return 0\n",
    "\n",
    "    def max_value(self, actions, map_state):\n",
    "        v = -100000\n",
    "        for act in actions:\n",
    "            map_state_copy = map_state.copy()\n",
    "            map_state_copy[act[0], act[1]] = 10\n",
    "            v = max(v, self.value('min', map_state_copy))\n",
    "        return v\n",
    "    def min_value(self, actions, map_state):\n",
    "        v = 100000\n",
    "        for act in actions:\n",
    "          map_state_copy = map_state.copy()\n",
    "          map_state_copy[act[0], act[1]] = 1\n",
    "          v = min(v, self.value('max', map_state_copy))\n",
    "        return v\n",
    "\n",
    "    def agent_pick(self):\n",
    "        actions = np.concatenate([(np.where(self.map == 0))], axis=1).T\n",
    "        if len(actions) > 0:\n",
    "            act_result = []\n",
    "            for act in actions:\n",
    "                map_state_copy = self.map.copy()\n",
    "                map_state_copy[act[0], act[1]] = 10\n",
    "                act_result.append((act[0], act[1], self.value('min', map_state_copy)))\n",
    "            act_result.sort(key=lambda x: x[2])\n",
    "            print(act_result)\n",
    "            act_choice = act_result.pop()\n",
    "            self.map[act_choice[0], act_choice[1]] = 10\n",
    "            print(\"Agent落子:\", act_choice[0], act_choice[1])\n",
    "        else:\n",
    "            print(\"Agent已经无处落子\")\n",
    "    def pick(self, x, y):\n",
    "        if self.map[x, y] == 0:\n",
    "            self.map[x, y] = 1\n",
    "            print('玩家落子:', x, y)\n",
    "            self.agent_pick()\n",
    "        else:\n",
    "            print('该点已经有棋子')\n",
    "        if self.check_win() == 1:\n",
    "            print(\"玩家胜利\")\n",
    "        elif self.check_win() == 2:\n",
    "            print(\"Agent胜利\")\n",
    "        self.draw()\n",
    "    \n",
    "game = MinimaxTicTacToe('MinimaxTictacToe')\n",
    "game.draw()\n",
    "game.pick(0,1)\n",
    "game.pick(1,1)\n",
    "game.pick(0,0)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "1a8a2049-6a9c-4dc2-8d73-53fbfbf54bcf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 320x240 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "玩家落子: 1 1\n",
      "[(0, 1, -1470), (1, 0, -1470), (1, 2, -1470), (2, 1, -1470), (0, 0, -1038), (0, 2, -1038), (2, 0, -1038), (2, 2, -1038)]\n",
      "Agent落子: 2 2\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 320x240 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "玩家落子: 2 1\n",
      "[(0, 0, -41), (1, 0, -39), (2, 0, -39), (0, 1, -32), (1, 2, -25), (0, 2, -9)]\n",
      "Agent落子: 0 2\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 320x240 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "arr [[0 1 1]\n",
      " [0 1 1]\n",
      " [1 0 1]]\n",
      "arr.sum(axis = 0) [1 2 3]\n",
      "arr.sum(axis = 1) [2 2 2]\n",
      "arr.trace() 2\n",
      "np.flip(arr,axis=1).trace() 3\n",
      "np.concatenate([np.where(arr==0)],axis=1).T [[0 0]\n",
      " [1 0]\n",
      " [2 1]]\n"
     ]
    }
   ],
   "source": [
    "# TicTacToe\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "\n",
    "plt.rcdefaults()\n",
    "plt.rcParams['figure.dpi'] = 50\n",
    "plt.rcParams['font.size'] = 20\n",
    "\n",
    "class Thing:\n",
    "    def __init__(self, name=''):\n",
    "        self.name = name\n",
    "    def __repr__(self):\n",
    "        return self.name\n",
    "\n",
    "class Problem(Thing):\n",
    "    def __init__(self, name):\n",
    "        super().__init__(name)\n",
    "\n",
    "class GameProblem(Problem):\n",
    "    def __init__(self, name):\n",
    "        super().__init__(name)\n",
    "    def check_win(self):\n",
    "        pass\n",
    "    \n",
    "class TicTacToe(GameProblem):\n",
    "    def __init__(self, name):\n",
    "        super().__init__(name)\n",
    "        self.map = np.zeros((3, 3))\n",
    "        # self.map = np.random.randint(0, 10, (3, 3))\n",
    "\n",
    "    def check_win(self, state_map=None):\n",
    "        if state_map is None:\n",
    "            state_map = self.map\n",
    "        check_map = np.concatenate([state_map.sum(axis=0),\n",
    "                                    state_map.sum(axis=1),\n",
    "                                    [state_map.trace()],\n",
    "                                    [np.flip(state_map, axis=1).trace()]])\n",
    "        if 3 in check_map:  # 玩家赢\n",
    "            return 1\n",
    "        elif 30 in check_map:  # Agent赢\n",
    "            return 2\n",
    "        else:\n",
    "            return 0\n",
    "\n",
    "    def draw(self):\n",
    "        sns.heatmap(self.map.clip(0, 2),\n",
    "                    cmap='Set3',\n",
    "                    center=0,\n",
    "                    annot=True,\n",
    "                    cbar=False)\n",
    "        plt.show()\n",
    "\n",
    "# WinPercent\n",
    "class WinPercentTicTacToe(TicTacToe):\n",
    "    def __init__(self, name):\n",
    "        super().__init__(name)\n",
    "\n",
    "    def value(self, next_agent, map_state):\n",
    "        win = self.check_win(map_state)\n",
    "        if win == 1:\n",
    "            return -1\n",
    "        elif win == 2:\n",
    "            return 1\n",
    "        actions = np.concatenate([(np.where(map_state == 0))], axis=1).T  # self.map\n",
    "        if len(actions) > 0:\n",
    "            if next_agent == 'max':\n",
    "                return self.max_value(actions, map_state)\n",
    "            elif next_agent == 'min':\n",
    "                return self.min_value(actions, map_state)\n",
    "        else:\n",
    "            return 0\n",
    "\n",
    "    def max_value(self, actions, map_state):\n",
    "        v = 0\n",
    "        for act in actions:\n",
    "            map_state_copy = map_state.copy()\n",
    "            map_state_copy[act[0], act[1]] = 10\n",
    "            v = v + self.value('min', map_state_copy)\n",
    "        return v\n",
    "    \n",
    "    def min_value(self, actions, map_state):\n",
    "        v = 0\n",
    "        for act in actions:\n",
    "            map_state_copy = map_state.copy()\n",
    "            map_state_copy[act[0], act[1]] = 1\n",
    "            v = v + self.value('max', map_state_copy)\n",
    "        return v\n",
    "\n",
    "    def agent_pick(self):\n",
    "        actions = np.concatenate([(np.where(self.map == 0))], axis=1).T\n",
    "        if len(actions) > 0:\n",
    "            act_result = []\n",
    "            for act in actions:\n",
    "                map_state_copy = self.map.copy()\n",
    "                map_state_copy[act[0], act[1]] = 10\n",
    "                act_result.append((act[0], act[1], self.value('min', map_state_copy)))\n",
    "            act_result.sort(key=lambda x: x[2])\n",
    "            print(act_result)\n",
    "            act_choice = act_result.pop()\n",
    "            self.map[act_choice[0], act_choice[1]] = 10\n",
    "            print(\"Agent落子:\", act_choice[0], act_choice[1])\n",
    "        else:\n",
    "            print(\"Agent已经无处落子\")\n",
    "    def pick(self, x, y):\n",
    "        if self.map[x, y] == 0:\n",
    "            self.map[x, y] = 1\n",
    "            print('玩家落子:', x, y)\n",
    "            self.agent_pick()\n",
    "        else:\n",
    "            print('该点已经有棋子')\n",
    "        if self.check_win() == 1:\n",
    "            print(\"玩家胜利\")\n",
    "        elif self.check_win() == 2:\n",
    "            print(\"Agent胜利\")\n",
    "        self.draw()     \n",
    "\n",
    "game = WinPercentTicTacToe('WinPercent')\n",
    "game.draw()\n",
    "game.pick(1,1)\n",
    "game.pick(2,1)\n",
    "arr = np.random.randint(0,2,(3,3))\n",
    "print('arr',arr)\n",
    "print('arr.sum(axis = 0)',arr.sum(axis = 0))\n",
    "print('arr.sum(axis = 1)',arr.sum(axis = 1))\n",
    "print('arr.trace()',arr.trace())\n",
    "print('np.flip(arr,axis=1).trace()',np.flip(arr,axis=1).trace())\n",
    "np.concatenate([arr.sum(axis=0),\n",
    "               arr.sum(axis=1),\n",
    "               [arr.trace(),\n",
    "                np.flip(arr,axis=1).trace()]])\n",
    "print('np.concatenate([np.where(arr==0)],axis=1).T',np.concatenate([np.where(arr==0)],axis=1).T)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "588f861b-a90e-42d7-8a54-860f66a09d41",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.21"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
